# -*- coding: utf-8 -*-
import os
from configparser import ConfigParser
import json

import copy

"""
project
    |
    process
        |
        function
                |
                group
                    |
                    parameter
"""


class FuncBlockManager:
    func_name = ""
    index = 0

    def __init__(self):
        self.index = 0
        self._para = dict()
        self._func_name = ""

    def save(self, func_name):
        with open(func_name, "w", encoding='utf-8') as f:
            f.write(json.dumps(self._para, indent=4))

    def open(self, fn):
        with open(fn, "r", encoding='utf-8') as f:
            g_para = json.loads(f.read())
        return g_para


class ProcessManager:
    process_name = ""
    index = 0

    def __init__(self):
        self._process_name = 0
        self.func_list: FuncBlockManager = []
        self.func_list.clear()
        self.index = 0

    def append(self, func):
        self.func_list.append(func)

    def save(self, dir_name):
        config = ConfigParser()
        config.add_section('info')
        process_len = len(self.func_list)
        config.set("info", "name", self.process_name)
        config.set("info", "num", "%d" % process_len)
        if process_len == 0:
            return
        config.add_section("function")
        for i in range(process_len):
            f_name = self.func_list[i].func_name + "_%d" % self.func_list[i].index
            config.set("function", "no_%d" % i, f_name)
        pr_name = self.process_name.replace(" ", "_")
        fo = open(os.path.join(dir_name, pr_name) + ".ini", 'w', encoding='UTF-8')
        config.write(fo)
        fo.close()
        for func in self.func_list:
            func_name = func.func_name.replace(' ', "_")
            f_name = func_name + "_%d" % func.index + ".json"
            f_nm = os.path.join(dir_name, f_name)
            func.save(f_nm)

    def open(self, p_name):
        config = ConfigParser()
        config.read(p_name, encoding='UTF-8')
        num = config.getint("info", "num")
        nm = config.get("info", "name")
        if num == 0:
            return
        cur_dir = os.path.split(p_name)
        self.process_name = nm
        for i in range(num):
            func = FuncBlockManager()
            func_name = config.get("function", "no_%d" % i)
            f_nm = os.path.join(cur_dir[0], func_name + '.json')
            func.func_name = func_name.split('_')[0]
            func._para = func.open(f_nm)
            self.func_list.append(func)


class ProjectManager(object):
    index = 0

    def __init__(self):
        self._PrjPath = "."
        self._PrjName = ""
        self._ProcessList: ProcessManager = []
        self.cur_proc: ProcessManager = None
        self.cur_func: FuncBlockManager = None

    def getProjectName(self):
        if self._PrjName:
            return self._PrjName
        else:
            return "NULL"

    def setProjectName(self, strname):
        self._PrjName = strname
        self._ProcessList.clear()

    def setProjectPath(self, path):
        self._PrjPath = path

    def getProjectPath(self):
        return self._PrjPath

    def createProject(self, prj_name):
        config = ConfigParser()
        config.add_section('info')
        config.set("info", "name", self._PrjName)
        config.set("info", "description", "")
        with open(prj_name + ".prj", "w", encoding='utf-8') as f:
            config.write(f)

    def saveProject(self):
        if self._PrjName:
            pj_name = self._PrjName.replace(" ", "_")
            dir_name = os.path.join(self._PrjPath, pj_name)
            if not os.path.exists(dir_name):
                os.mkdir(dir_name)
            self.createProject(dir_name)
            process_len = len(self._ProcessList)
            config = ConfigParser()
            config.add_section('info')
            config.set("info", "name", pj_name)
            config.set("info", "num", "%d" % process_len)
            config.add_section("process")
            if process_len == 0:
                return
            for i in range(process_len):
                config.set("process", "no_%d" % i, self._ProcessList[i].process_name)
            fo = open(os.path.join(dir_name, pj_name) + ".ini", 'w', encoding='UTF-8')
            config.write(fo)
            fo.close()

            for process in self._ProcessList:
                proc_name = process.process_name.replace(' ', "_")
                p_dir_name = os.path.join(dir_name, proc_name)
                if not os.path.exists(p_dir_name):
                    os.mkdir(p_dir_name)
                process.save(p_dir_name)

    def openProject(self, pj_name):
        self._ProcessList.clear()
        if pj_name:
            pj_dir = os.path.split(pj_name)
            self._PrjPath = pj_dir[0]
        config = ConfigParser()
        config.read(pj_name, encoding='UTF-8')
        self._PrjName = config.get("info", "name")
        project_dir = os.path.join(self._PrjPath, self._PrjName)
        project_name = os.path.join(project_dir, self._PrjName + '.ini')
        config.read(project_name)
        process_num = config.getint('info', 'num')
        for i in range(process_num):
            process = ProcessManager()
            process_name = config.get("process", "no_%d" % i)
            process_dir = os.path.join(project_dir, process_name.replace(" ", "_"))
            nm = os.path.join(process_dir, process_name.replace(" ", "_") + '.ini')
            process.open(nm)
            self._ProcessList.append(process)
        for proc in self._ProcessList:
            proc.index = self.index
            self.index += 1
            for func in proc.func_list:
                func.index = self.index
                self.index += 1
        self.cur_proc = self._ProcessList[0]

    def closeProject(self):
        pass

    def getProcessList(self):
        return self._ProcessList

    def addProcess(self, proc_name):
        self.cur_proc = ProcessManager()
        self.cur_proc.process_name = proc_name
        self.cur_proc.index = self.index
        self._ProcessList.append(self.cur_proc)
        self.index += 1

    def addDevice(self, func_name, para):
        self.cur_func = FuncBlockManager()
        self.cur_func.func_name = func_name
        self.cur_func._para = para
        self.cur_func.index = self.index
        self.index += 1
        if self.cur_proc:
            self.cur_proc.append(self.cur_func)

    def addFunction(self, func_name, para):
        self.cur_func = FuncBlockManager()
        self.cur_func.func_name = func_name
        self.cur_func._para = para
        self.cur_func.index = self.index
        self.index += 1
        if self.cur_proc:
            self.cur_proc.append(self.cur_func)

    def getFunctionParas(self, index: int):
        for proc in self._ProcessList:
            for func in proc.func_list:
                if index == func.index:
                    return func._para
        return None

    def getIndex(self):
        return self.index

    def updateModulePara(self, module_index: int, module_para: dict):
        for proc in self._ProcessList:
            for func in proc.func_list:
                if module_index == func.index:
                    func._para = copy.deepcopy(module_para)
                    break

    def append(self, process):
        self._ProcessList.append(process)

    def deleteModule(self, module_index: int, module_name: str):
        len_proc = len(self._ProcessList)
        for proc in range(len_proc):
            if self._ProcessList[proc].index == module_index and self._ProcessList[proc].process_name == module_name:
                del self._ProcessList[proc]
                return
            len_func = len(self._ProcessList[proc].func_list)
            for func in range(len_func):
                if module_index == self._ProcessList[proc].func_list[func].index and \
                        self._ProcessList[proc].func_list[func].func_name == module_name:
                    print("del")
                    del self._ProcessList[proc].func_list[func]
                    return


if __name__ == "__main__":
    fb1 = FuncBlockManager()
    fb1.index = 1
    fb1.func_name = "image"
    fb1._para = {'x': "99", "y": "88"}

    fb2 = FuncBlockManager()
    fb2.index = 2
    fb2.func_name = "binary"
    fb2._para = {'x': "99", "y": "88"}

    pm1 = ProcessManager()
    pm1.process_name = "search center"
    pm1.append(fb1)
    pm1.append(fb2)

    fb3 = FuncBlockManager()
    fb3.index = 4
    fb3.func_name = "image"
    fb3._para = {'x': "99", "y": "88"}

    pm2 = ProcessManager()
    pm2.process_name = "demo"
    pm2.append(fb3)

    pj = ProjectManager()
    pj.setProjectName("wafer")
    pj.append(pm1)
    pj.append(pm2)

    pj.saveProject()
